/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using MyPhotoIndex.Importer.CameraImageAcquisition;
using System.Collections.ObjectModel;
using MyPhotoIndex.Importer;
using MyPhotoIndex.ImageBank.Query;
using MyPhotoIndex.ImageBank;
using MyPhotoIndex.Utilities;
using MyPhotoIndex.Settings;
using MyPhotoIndex.Controls;
using MyPhotoIndex.Interfaces.Tagging;
using MyPhotoIndex.Wizards.Import;
using MyPhotoIndex.Plugins.DataProviders;
using MyPhotoIndex.DataAccess;

namespace MyPhotoIndex.Wizards.CameraImport
{
    public partial class CameraImportWizard : WizardHost
    {
        private const int WizardPage_Welcome = 0;
        private const int WizardPage_DisplayImages = 1;
        private const int WizardPage_Setings = 2;
        private const int WizardPage_Transfer = 3;
        private const int WizardPage_Finish = 4;

        private ImagingDevice           m_camera;
        private FileImageDataImporter   m_importer;
        private String                  m_importBatchId;
        private String                  m_destinationPath;

        private bool                    m_tagImportedImages;
        private IImageTag               m_tagsExistingTag;
        private string                  m_tagsNewTagName;

        public CameraImportWizard()
        {
            InitializeComponent();

            this.Load += new EventHandler(CameraImportWizard_Load);

            base.PageNumberChangedEvent += new EventHandler<PageNumberChangedEventArgs>(CameraImportWizard_PageNumberChangedEvent);
            base.WizardFinishedEvent += new EventHandler(CameraImportWizard_WizardFinishedEvent);
            base.NumberOfPages = 5;

            SelectAllButton.Click+=new EventHandler(SelectAllButton_Click);
            ClearButton.Click+=new EventHandler(ClearButton_Click);

            btnBrowseFolder.Click += new EventHandler(btnBrowseFolder_Click);

            cmbCameraList.SelectedValueChanged += new EventHandler(cmbCameraList_SelectedValueChanged);

            tagImagesCheckBox.CheckedChanged += new EventHandler(tagImagesCheckBox_CheckedChanged);
            newTagNameRadioButton.CheckedChanged += new EventHandler(tagImagesCheckBox_CheckedChanged);
            existingTagRadioButton.CheckedChanged += new EventHandler(tagImagesCheckBox_CheckedChanged);

            m_importBatchId = Guid.NewGuid().ToString();
        }

        void CameraImportWizard_Load(object sender, EventArgs e)
        {
            NextButton.Enabled = false;
            BuildCameraList();

            base.SetPageNextButtonText(WizardPage_Setings, Resources.Resources.CameraImportWizard_Transfer);
            
            UpdateTagCreationButtonsStatus();
        }

        void CameraImportWizard_PageNumberChangedEvent(object sender, PageNumberChangedEventArgs e)
        {
            if (e.PageNumber == WizardPage_DisplayImages &&
                e.PageNumberBefore == WizardPage_Welcome)
            {
                base.DisableButtons();

                this.Cursor = Cursors.WaitCursor;
                myPhotoIndexThumbnailViewer1.ImageList = null;
                myPhotoIndexThumbnailViewer1.Refresh();

                m_camera = (ImagingDevice)cmbCameraList.SelectedItem;
                m_camera.ThumbnailDownloadEvent += new EventHandler<ImagingDeviceImageTransferEventArgs>(camera_ThumbnailDownloadEvent);
                CameraImageDownloadForm downloadForm = new CameraImageDownloadForm(m_camera);
                downloadForm.ShowDialog(this);

                myPhotoIndexThumbnailViewer1.ImageList = new AcquiredImageCollection(m_camera.Images);
                myPhotoIndexThumbnailViewer1.ScrollbarVisible = true;
                myPhotoIndexThumbnailViewer1.CheckAll();
                this.Cursor = Cursors.Default;

                int numOfImages = myPhotoIndexThumbnailViewer1.ImageList.Count;
                //xxx Items have been selected.
                imagesFoundLabel.Text = String.Format(Resources.Resources.CameraImportWizard_NumberOfImagesFound, numOfImages);

                base.EnableButtons();
            }

            if (e.PageNumber == WizardPage_Setings &&
                e.PageNumberBefore == WizardPage_DisplayImages)
            {

                BuildExistingTagsList();

                if (ApplicationFolders.UseCentralStorage == false)
                {
                    if (String.IsNullOrEmpty(ApplicationSettings.Default.DefaultImagesPath) == true)
                    {
                        ApplicationSettings.Default.DefaultImagesPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
                        DynamicConfiguration.Default.Save();
                    }

                    if (String.IsNullOrEmpty(m_destinationPath) == true)
                    {
                        m_destinationPath = ApplicationSettings.Default.DefaultImagesPath;
                    }
                }
                else
                {
                    tbDestinationPath.ReadOnly = true;
                    cbCreateSubFolder.Visible = false;
                    m_destinationPath = ApplicationFolders.CentralStorageLocation;
                    btnBrowseFolder.Visible = false;
                }

                tbDestinationPath.Text = m_destinationPath;
                cbDeleteAfterTransfer.Checked = ApplicationSettings.Default.DeleteImagesAfterTransfer;
            }

            if (e.PageNumber == WizardPage_Transfer &&
                e.PageNumberBefore == WizardPage_Setings)
            {
                base.DisableButtons();

                #region tags creatation settings
                if (tagImagesCheckBox.Checked == true)
                {
                    m_tagImportedImages = true;
                    if (newTagNameRadioButton.Checked == true)
                    {
                        m_tagsNewTagName = newTagNameTextBox.Text.Trim();
                    }
                    else
                        if (existingTagRadioButton.Checked == true)
                        {
                            m_tagsExistingTag = ((ExistingTagListItem)existingTagsComboBox.SelectedItem).Tag;
                        }
                }
                else
                {
                    m_tagImportedImages = false;
                }
                #endregion

                importingFileLabel.Text = String.Empty;

                String downloadPath = m_destinationPath;
                if (cbCreateSubFolder.Checked == true)
                {
                    DateTime cd = DateTime.Now;
                    object[] dateParts = new object[] { cd.Year, cd.Month, cd.Day, cd.Hour, cd.Minute, cd.Second };
                    String nowFolderName = String.Format("{0}-{1}-{2}-{3}{4}-{5}", dateParts);
                    downloadPath = Path.Combine(downloadPath, nowFolderName);
                }

                try
                {
                    Directory.CreateDirectory(downloadPath);
                }
                catch(Exception ex)
                {//Handle error here
                    Logger.Log(ex);
                }

                this.Cursor = Cursors.WaitCursor;
                int numOfImagesToImport = myPhotoIndexThumbnailViewer1.CheckedImages.Count;
          
                progressBar1.Maximum = numOfImagesToImport;
                String[] importedFiles = new String[numOfImagesToImport];

                int ii = 0;
                int currentImage = 0;
                List<IAcquiredImage> transferedImages = new List<IAcquiredImage>();
                foreach (IAcquiredImage image in m_camera.Images)
                {
                    if (myPhotoIndexThumbnailViewer1.CheckedImages.Contains(currentImage++) == true)
                    {
                        importingFileLabel.Text = image.Name;
                        pictureBox1.Image = image.Thumbnail;

                        Application.DoEvents();

                        String imagePath = Path.Combine(downloadPath, image.Name);
                        imagePath = Path.ChangeExtension(imagePath, image.FileExtention);
                        try
                        {
                            image.Transfer(imagePath);
                            importedFiles[ii] = imagePath;
                        }
                        catch(Exception ex)
                        {//ToDo: list errors here
                            Logger.Log(ex);
                        }

                        progressBar1.Value = ++ii;
                        transferedImages.Add(image);
                    }
                }

                if (cbDeleteAfterTransfer.Checked == true)
                {
                    importingFileLabel.Text = Resources.Resources.CameraImportWiz_DeletingImages;
                    ii = 0;
                    progressBar1.Value = 0;
                    progressBar1.Maximum = transferedImages.Count;
                    foreach (IAcquiredImage image in transferedImages)
                    {
                        image.Delete();
                        progressBar1.Value = ++ii;
                        Application.DoEvents();
                    }
                }

                progressBar1.Value = 0;
                progressBar1.Maximum = importedFiles.Length;
                m_importer = new FileImageDataImporter(m_importBatchId);
                m_importer.SetImageTagsEvent += new EventHandler<SetImageTagsEventArgs>(m_importer_SetImageTagsEvent);
                m_importer.ImageDataImporterProcessEvent += new EventHandler<ImageDataImporterEventArgs>(m_importer_ImageDataImporterProcessEvent);

                m_importer.ImportFromFileList(importedFiles, ApplicationSettings.Default.CachedThumbnailSize);
                this.Cursor = Cursors.Default;

                base.EnableButtons();
                base.CloseButton.Visible = false;
                base.BackButton.Visible = false;
                NextButtonClick(this, EventArgs.Empty);
            }

            if (e.PageNumber == WizardPage_Finish &&
                e.PageNumberBefore == WizardPage_Transfer)
            {
                if (m_importer.Errors.Count == 0)
                {
                    errorLabel.Visible = false;
                    listBox2.Visible = false;
                }
                else
                {
                    foreach (ImageImportException ex in m_importer.Errors)
                    {
                        try
                        {
                            listBox2.Items.Add(ex.FileName);
                        }
                        catch
                        {
                        }
                    }
                }
            }
        }

        void m_importer_ImageDataImporterProcessEvent(object sender, ImageDataImporterEventArgs e)
        {
            progressBar1.Value = e.FileOffset;
            Application.DoEvents();
        }

        protected override void NextButtonClick(object sender, EventArgs e)
        {
            if (PageNumber == WizardPage_Welcome)
            {
                if (cmbCameraList.SelectedItem == null)
                {
                    ApplicationAlert.Show(Resources.Resources.FileImportWizard_MustSelect);
                    return;
                }
            }

            if (PageNumber == WizardPage_Setings)
            {
                if (tagImagesCheckBox.Checked == true)
                {
                    if (newTagNameRadioButton.Checked == true)
                    {
                        if (string.IsNullOrEmpty(newTagNameTextBox.Text.Trim()) == true)
                        {
                            ApplicationAlert.Show(Resources.Resources.FileImportWizard_InvalidNewTagName, Resources.Resources.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                            return;
                        }
                    }
                    else
                    {
                        if (existingTagsComboBox.SelectedIndex == 0)
                        {
                            ApplicationAlert.Show(Resources.Resources.FileImportWizard_selectTag, Resources.Resources.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                            return;
                        }
                    }
                }
            }

            base.NextButtonClick(sender, e);
        }

        void camera_ThumbnailDownloadEvent(object sender, ImagingDeviceImageTransferEventArgs e)
        {
            ImagingDevice imagingDevice = (ImagingDevice)sender;
            imagesFoundLabel.Text = String.Format(Resources.Resources.CameraImportWizard_NumberOfImagesFound, imagingDevice.Images.Count);
        }

        private void BuildCameraList()
        {
            cmbCameraList.Items.Clear();
            foreach (ImagingDevice camera in DigitalCamera.List)
            {
                cmbCameraList.Items.Add(camera);
            }

            String lastCamera = ApplicationSettings.Default.LastCameraImport;
            int item = -1;
            if (String.IsNullOrEmpty(lastCamera) == false)
            {
                item = cmbCameraList.FindString(lastCamera);
            }

            if (-1 == item
                && cmbCameraList.Items.Count > 0)
            {
                cmbCameraList.SelectedIndex = 0;
                NextButton.Enabled = true;
            }
            else
            {
                cmbCameraList.SelectedIndex = item;
            }
        }

        private void btnBrowseFolder_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBrowse = new FolderBrowserDialog();
            folderBrowse.SelectedPath = tbDestinationPath.Text;
            folderBrowse.ShowDialog(this);
            tbDestinationPath.Text = folderBrowse.SelectedPath;

            ApplicationSettings.Default.DefaultImagesPath = tbDestinationPath.Text;
            m_destinationPath = tbDestinationPath.Text;
            DynamicConfiguration.Default.Save();
        }

        private void cmbCameraList_SelectedValueChanged(object sender, EventArgs e)
        {
            if (cmbCameraList.SelectedItem != null)
            {
                NextButton.Enabled = true;
            }
        }

        void CameraImportWizard_WizardFinishedEvent(object sender, EventArgs e)
        {
            ApplicationSettings.Default.DeleteImagesAfterTransfer = cbDeleteAfterTransfer.Checked;
            if (cmbCameraList.SelectedItem != null)
            {
                ApplicationSettings.Default.LastCameraImport = cmbCameraList.SelectedItem.ToString();
            }
            ApplicationSettings.Default.Save();

            ImageTagCollection.Instance.Load((ITagsDataAccessProvider)DataAccessProvider.Instance);

            QueryParameter[] queryParameters = new QueryParameter[] { new ImageBatchQueryParameter(m_importBatchId) };
            Storage.Instance.LoadImageList();
            Storage.Instance.Filter(queryParameters);
        }

        private void SelectAllButton_Click(object sender, EventArgs e)
        {
            myPhotoIndexThumbnailViewer1.CheckAll();
        }

        private void ClearButton_Click(object sender, EventArgs e)
        {
            myPhotoIndexThumbnailViewer1.ClearChecked();
        }

        private void BuildExistingTagsList()
        {
            existingTagsComboBox.Items.Clear();
            existingTagsComboBox.Items.Add(Resources.Resources.FileImportWizard_SelectTagCombo);
            existingTagsComboBox.SelectedIndex = 0;

            BuildExistingTagsList(0, ImageTagCollection.Instance.Tags);
        }

        private void BuildExistingTagsList(int level, List<IImageTag> tagList)
        {
            foreach (IImageTag tag in tagList)
            {
                existingTagsComboBox.Items.Add(new ExistingTagListItem(tag, level));

                BuildExistingTagsList(level + 1, tag.ChildTags);
            }
        }

        private void UpdateTagCreationButtonsStatus()
        {
            if (tagImagesCheckBox.Checked == true)
            {
                newTagNameRadioButton.Enabled = true;
                existingTagRadioButton.Enabled = true;

                newTagNameTextBox.Enabled = (newTagNameRadioButton.Checked == true);
                existingTagsComboBox.Enabled = (existingTagRadioButton.Checked == true);
            }
            else
            {
                newTagNameRadioButton.Enabled = false;
                newTagNameTextBox.Enabled = false;
                existingTagRadioButton.Enabled = false;
                existingTagsComboBox.Enabled = false;
            }
        }

        void tagImagesCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            UpdateTagCreationButtonsStatus();
        }

        void m_importer_SetImageTagsEvent(object sender, SetImageTagsEventArgs e)
        {
            if (m_tagImportedImages == true)
            {
                if (m_tagsExistingTag == null)
                {
                    TaggingAssistant taggingAssistant = new TaggingAssistant(m_tagsNewTagName);
                    e.ImageTags.Add(taggingAssistant.Tag);
                }
                else
                {
                    e.ImageTags.Add(m_tagsExistingTag);
                }
            }
        }
    }
}